package com.alameda.common.config.interceptors;

import com.alameda.common.exception.BusinessException;
import com.alameda.common.result.ResultEnum;
import com.alameda.common.utils.PubUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.Instant;

/**
 * 接口安全拦截器
 *
 * @author Lv
 * @date 2024/7/6
 */
@Slf4j
@Order(1)
@Component
public class ApiSecureInterceptor implements HandlerInterceptor {

    /**
     * 是否需要水平越权校验
     */
    @Value("${level-power}")
    private Boolean powerKey;

    /**
     * 前置处理 判断是否包含请求key
     *
     * @param httpServletRequest  http请求对象
     * @param httpServletResponse http响应对象
     * @param handler             处理器对象
     * @return 是否放行请求
     */
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
        if (powerKey) {
            // 获取请求key
            String requestKey = httpServletRequest.getHeader("requestKey");
            // 校验请求是否允许
            checkRequestKey(requestKey);
        }
        // 放行请求
        return true;
    }

    /**
     * 误差范围
     */
    @Value("${error-range}")
    private Integer errorRange;

    /**
     * 校验水平越权key (接口防刷机制)
     *
     * @param requestKey 水平越权key
     */
    private void checkRequestKey(String requestKey) {
        if (PubUtils.isEmpty(requestKey)) {
            BusinessException.throwException(ResultEnum.NO_OPERATOR_AUTH);
        }

        Instant instant = Instant.now();
        long epochSecond = instant.getEpochSecond();
        log.info("epochSecond [{}] requestKey[{}]", epochSecond, requestKey);

        // 时间设定在误差允许范围内可访问  误差范围2
        if (epochSecond - Long.parseLong(requestKey) > errorRange) {
            BusinessException.throwException(ResultEnum.NO_OPERATOR_AUTH);
        }
    }
}
